package tech.heptagram.staff.tools.service;

import com.github.pagehelper.PageInfo;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import tech.heptagram.core.common.rest.ResponseResult;
import tech.heptagram.core.common.rest.RestResultEnum;
import tech.heptagram.staff.exception.StaffApiException;
import tech.heptagram.staff.model.Staff;
import tech.heptagram.staff.model.StaffAuthException;
import tech.heptagram.staff.query.StaffQuery;
import tech.heptagram.staff.query.StaffQueryBuilder;
import tech.heptagram.staff.query.StaffRemoveReq;
import tech.heptagram.staff.query.StaffSaveReq;
import tech.heptagram.staff.service.BpmsProcessService;
import tech.heptagram.staff.service.DepartmentService;
import tech.heptagram.staff.service.ProcessRecordService;
import tech.heptagram.staff.service.StaffService;

/**
 * @author wang.yuchuan
 * @date 2018/9/5
 */
@Slf4j
public class StaffServiceRestTemplateImpl extends AbstractServiceImpl implements StaffService {

    private RestTemplate restTemplate;

    @Getter
    @Setter
    private DepartmentService departmentService;

    @Getter
    @Setter
    private BpmsProcessService bpmsProcessService;

    @Getter
    @Setter
    private ProcessRecordService processRecordService;

    public StaffServiceRestTemplateImpl(String staffApiDomain, RestTemplate restTemplate) {
        super(staffApiDomain);
        this.restTemplate = restTemplate;
    }

    @Override
    public DepartmentService getDepartmentService() {
        return departmentService;
    }

    @Override
    public BpmsProcessService getBpmsProcessService() {
        return bpmsProcessService;
    }

    @Override
    public ProcessRecordService getProcessRecordService() {
        return processRecordService;
    }

    @Override
    public String saveStaff(StaffSaveReq staffSaveReq) {
        log.info("请求 保存员工信息 接口: {}", staffSaveReq);

        String saveStaffUrl = getStaffApiDomainUrl() + "/api/v3/staff/save";

        RequestEntity<StaffSaveReq> requestEntity = RequestEntity.post(URI.create(saveStaffUrl))
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .body(staffSaveReq);

        ParameterizedTypeReference<ResponseResult<String>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<String>>() {
        };
        ResponseEntity<ResponseResult<String>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求 保存员工信息接口 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public void updateStaff(StaffSaveReq staffSaveReq) {
        log.info("请求 修改员工信息 接口: {}", staffSaveReq);

        String updateStaffUrl = getStaffApiDomainUrl() + "/api/v3/staff/update";

        RequestEntity<StaffSaveReq> requestEntity = RequestEntity.post(URI.create(updateStaffUrl))
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .body(staffSaveReq);

        ParameterizedTypeReference<ResponseResult> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult>() {
        };
        ResponseEntity<ResponseResult> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求 修改员工信息接口 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
    }

    @Override
    public Staff auth(String account, String password) throws StaffAuthException {
        if (StringUtils.isEmpty(account)) {
            throw new StaffAuthException("用户名为空");
        }
        if (StringUtils.isEmpty(password)) {
            throw new StaffAuthException("用户密码为空");
        }
        log.info("请求员工账号认证接口auth: account:{} password:{}", account, password);

        String url = getStaffApiDomainUrl() + "/api/v3/staff/auth/" + account + "/" + password;

        RequestEntity<Object> requestEntity = RequestEntity.post(URI.create(url))
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(null);

        ParameterizedTypeReference<ResponseResult<Staff>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<Staff>>() {
        };
        ResponseEntity<ResponseResult<Staff>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);
        log.info("请求员工账号认证接口auth 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public void updateStaffNickname(String staffCode, String nickName) {
        log.info("请求 更新员工花名 接口 updateStaffNickname: code:{} nickName:{}", staffCode, nickName);

        Staff updateStaff = new Staff();
        updateStaff.setCode(staffCode);
        updateStaff.setNickName(nickName);

        String updateStaffNicknameUrl = getStaffApiDomainUrl() + "/api/v3/staff/modify/nickname";

        RequestEntity<Staff> requestEntity = RequestEntity.post(URI.create(updateStaffNicknameUrl))
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(updateStaff);

        ParameterizedTypeReference<ResponseResult> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult>() {
        };
        ResponseEntity<ResponseResult> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求 更新员工花名 接口 updateStaffNickname: 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
    }

    @Override
    public PageInfo<Staff> findStaffsWithPage(StaffQuery staffQuery) {
        log.info("请求查询员工列表接口findStaffsWithPage: {}", staffQuery);

        String findStaffsUrl = getStaffApiDomainUrl() + "/api/v3/staff/listpage";

        RequestEntity<StaffQuery> requestEntity = RequestEntity.post(URI.create(findStaffsUrl))
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(staffQuery);

        ParameterizedTypeReference<ResponseResult<PageInfo<Staff>>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<PageInfo<Staff>>>() {
        };
        ResponseEntity<ResponseResult<PageInfo<Staff>>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求查询员工列表接口findStaffsWithPage返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public List<Staff> findStaffs(StaffQuery staffQuery) {

        log.info("请求查询员工列表接口findStaffs: {}", staffQuery);

        String findStaffsUrl = getStaffApiDomainUrl() + "/api/v3/staff/list";

        RequestEntity<StaffQuery> requestEntity =  RequestEntity.post(URI.create(findStaffsUrl))
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(staffQuery);

        ParameterizedTypeReference<ResponseResult<List<Staff>>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<List<Staff>>>() {
        };
        ResponseEntity<ResponseResult<List<Staff>>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求查询员工列表接口findStaffs返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public List<Staff> findByStaffCodes(List<String> staffCodes) {
        if(CollectionUtils.isEmpty(staffCodes)) {
            return new ArrayList<>();
        }

        StaffQuery staffQuery = StaffQueryBuilder.builder().staffCodes(staffCodes).build();
        return findStaffs(staffQuery);
    }

    @Override
    public Staff getStaff(StaffQuery staffQuery) {

        log.info("请求查询员工信息接口:{}", staffQuery);
        String getStaffUrl = getStaffApiDomainUrl() + "/api/v3/staff/get";

        RequestEntity<StaffQuery> requestEntity =  RequestEntity.post(URI.create(getStaffUrl))
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .body(staffQuery);

        ParameterizedTypeReference<ResponseResult<Staff>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<Staff>>() {
        };
        ResponseEntity<ResponseResult<Staff>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求查询员工信息接口返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public Staff getByCode(String staffCode) {
        StaffQuery staffQuery = StaffQueryBuilder.builder().staffCode(staffCode).build();
        return getStaff(staffQuery);
    }

    @Override
    public Staff getByName(String staffName) {
        StaffQuery staffQuery = StaffQueryBuilder.builder().staffName(staffName).build();
        return getStaff(staffQuery);
    }

    @Override
    public Staff getByMobile(String mobile) {
        StaffQuery staffQuery = StaffQueryBuilder.builder().mobile(mobile).build();
        return getStaff(staffQuery);
    }

    @Override
    public Staff getByWxUserId(String wxUserId) {
        StaffQuery staffQuery = StaffQueryBuilder.builder().wxUserId(wxUserId).build();
        return getStaff(staffQuery);
    }

    @Override
    public Staff getByDingtalkId(String dingtalkId) {
        StaffQuery staffQuery = StaffQueryBuilder.builder().dingtalkId(dingtalkId).build();
        return getStaff(staffQuery);
    }

    @Override
    public Staff getByNickName(String nickName) {

        String getStaffUrl = getStaffApiDomainUrl() + "/api/v3/staff/get/nickname/" + nickName;
        log.info("请求根据花名查找员工信息接口: nickName: {} url: {}", nickName, getStaffUrl);

        RequestEntity<Void> requestEntity = RequestEntity.get(URI.create(getStaffUrl))
            .accept(MediaType.APPLICATION_JSON)
            .build();

        ParameterizedTypeReference<ResponseResult<Staff>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<Staff>>() {
        };

        ResponseEntity<ResponseResult<Staff>> resultEntity = restTemplate.exchange(getStaffUrl, HttpMethod.GET, requestEntity, responseResultParameterizedTypeReference);

        log.info("请求根据花名查找员工信息接口 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
        return resultEntity.getBody().getData();
    }

    @Override
    public void updateStaffStatus(StaffRemoveReq req) {
        log.info("请求 修改员工离职状态 接口参数 req:{}",req);

        String updateStaffStatusUrl = getStaffApiDomainUrl() + "/api/v3/staff/update/status";

        RequestEntity<StaffRemoveReq> requestEntity = RequestEntity.post(URI.create(updateStaffStatusUrl))
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .body(req);

        ParameterizedTypeReference<ResponseResult> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult>() {
        };
        ResponseEntity<ResponseResult> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        log.info("请求 修改员工离职状态 接口 updateStaffStatus: 返回结果:{}", resultEntity.getBody().toString());
        if (resultEntity.getBody().getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }
    }

    /**
     * 根据部门ID查询员工列表
     *
     * @param departmentId 部门ID
     * @return 员工列表
     */
    @Override
    public List<Staff> getByDepartmentId(Integer departmentId) {
        log.info("请求根据部门ID查询员工列表接口: departmentId:{} ", departmentId);

        String url = getStaffApiDomainUrl() + "/api/v3/staff/get/departmentId/" + departmentId;

        RequestEntity<Void> requestEntity = RequestEntity.get(URI.create(url))
                .accept(MediaType.APPLICATION_JSON)
                .build();

        ParameterizedTypeReference<ResponseResult<List<Staff>>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<List<Staff>>>() {};
        ResponseEntity<ResponseResult<List<Staff>>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        if (Objects.requireNonNull(resultEntity.getBody()).getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }

        log.info("请求根据部门ID查询员工列表接口 返回结果:{}", resultEntity.getBody());
        return resultEntity.getBody().getData();
    }

    /**
     * 根据部门ID列表查询员工CODE列表
     *
     * @param deptIdList 部门ID列表
     * @return 员工CODE列表
     */
    @Override
    public List<String> getStaffCodeListByDeptIdList(List<Integer> deptIdList) {
        log.info("请求 根据部门ID列表查询员工编码列表 接口: deptIdList:{} ", deptIdList);

        String url = getStaffApiDomainUrl() + "/api/v3/staff/get/staffCodeList";

        RequestEntity<Object[]> requestEntity = RequestEntity.post(URI.create(url))
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(deptIdList.toArray());
        log.info("requestEntity: {}", requestEntity);

        ParameterizedTypeReference<ResponseResult<List<String>>> responseResultParameterizedTypeReference = new ParameterizedTypeReference<ResponseResult<List<String>>>() {};
        ResponseEntity<ResponseResult<List<String>>> resultEntity = restTemplate.exchange(requestEntity, responseResultParameterizedTypeReference);

        if (Objects.requireNonNull(resultEntity.getBody()).getRetcode() != RestResultEnum.SUCCESS.getKey()) {
            throw new StaffApiException(resultEntity.getBody().getMsg());
        }

        log.info("请求 根据部门ID列表查询员工编码列表 接口 返回结果:{}", resultEntity.getBody());
        return resultEntity.getBody().getData();
    }
}
